package com.sky.aspect;

import com.sky.context.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Aspect
@Slf4j
@Component
public class CommonFieldAspect {

    public List<String> save = Arrays.asList("createTime", "updateTime", "createUser", "updateUser", "status");

    public List<String> update = Arrays.asList("updateTime", "updateUser");

    public void common(ProceedingJoinPoint pjp, List<String> names) {
        Object[] args = pjp.getArgs();
        Arrays.stream(args).forEach(arg -> {
            Class<?> aClass = arg.getClass();
            names.forEach(s -> {
                  Field field = null;
                try {
                    field = aClass.getDeclaredField(s);
                } catch (NoSuchFieldException e) {
                    log.info(e.getMessage());
                }
                if (null == field)
                    return;
                field.setAccessible(true);
                Class<?> declaringClass = field.getType();
                try {
                    if (LocalDateTime.class.equals(declaringClass)) {
                        field.set(arg, LocalDateTime.now());
                    } else if (Long.class.equals(declaringClass)) {
                        field.set(arg, BaseContext.getCurrentId());
                    } else if (Integer.class.equals(declaringClass)) {
                        field.set(arg, 1);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            });
        });
    }

    @Around("@annotation(com.sky.aspect.annotation.SaveCommonFieldAnno)")
    public Object saveAround(ProceedingJoinPoint pjp) throws Throwable {
        common(pjp, save);
        Object proceed = pjp.proceed();
        return proceed;
    }

    @Around("@annotation(com.sky.aspect.annotation.UpdateCommonFieldAnno)")
    public Object updateAround(ProceedingJoinPoint pjp) throws Throwable {
        common(pjp, update);
        Object proceed = pjp.proceed();
        return proceed;
    }
}
